﻿/*
   Copyright 2011 Andrew Davis

    This file is part of Base.

    Base is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Base is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Base.  If not, see <http://www.gnu.org/licenses/>.
*/
namespace Base.Prototypes
{
	using System;
	using System.Collections.Generic;
	using System.ComponentModel;

	/// <summary>
	/// Prototype for the derived BaseLits to follow.
	/// </summary>
	/// <typeparam name="T">A class which derives from the BaseClass</typeparam>
	[Serializable()]
	public abstract class BaseList<T> : List<T> where T : BaseClass
	{
		#region "Public Events"
		/// <summary>
		/// This is fired when a property is changed.  The 'PropertyName' of the listener is whatever is passed into the NotifyPropertyChanged method. 
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;
		#endregion

		#region "Private Variables"
		/// <summary>
		/// The flag of the current status of the object
		/// </summary>
		protected ObjectStatus objectStatus;
		#endregion

		#region "Protected Methods"
		/// <summary>
		/// Updates the ObjectStatus if it needs to and then raises a PropertyChanged event
		/// </summary>
		/// <param name="info">The parameter to flag the listener with.</param>
		protected void NotifyPropertyChanged(String info)
		{
			if (objectStatus == ObjectStatus.Unchanged)
				objectStatus = ObjectStatus.IsDirty;
			if (PropertyChanged != null)
				PropertyChanged(this, new PropertyChangedEventArgs(info));
		}
		/// <summary>
		/// Listener to the PropertyChanged event
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void bc_PropertyChanged(object sender, PropertyChangedEventArgs e)
		{
			NotifyPropertyChanged(e.PropertyName);
		}
		#endregion

		#region "CRUD"
		/// <summary>
		/// This method is the entry point to the create, update and delete methods.  Which one fires depends on the status of the object.
		/// The properties of the class is picked up and used as parameters for the SQL call.
		/// </summary>
		/// <param name="connStr">The connection string to the data source</param>
		/// <param name="additionalParams">Futher arguments for the SQL call that are not properties of the object</param>
		/// <returns>Whether the database transaction was successful</returns>
		public bool Update(String connStr, object additionalParams = null)
		{
			bool result = true;
			if (objectStatus == ObjectStatus.Unchanged)
				return result;
	
			foreach (T bc in this)
			{
				result = bc.Update(connStr, additionalParams);
				if (!result)
					return false;
			}
			objectStatus = ObjectStatus.Unchanged;
			return true;
		}
		#endregion

		#region "Public Methods"
		/// <summary>
		/// Adds a listener to the PropertyChanged event to each object it contains
		/// </summary>
		public void AddEventHandler()
		{
			foreach (T bc in this)
				bc.PropertyChanged += new PropertyChangedEventHandler(bc_PropertyChanged);
		}
		/// <summary>
		/// Adds an object to the list, adds the listener and raises the event.
		/// If adding a 'new' object to the list this method must be used.
		/// </summary>
		/// <param name="bc"></param>
		public void AddNew(T bc)
		{
			this.Add(bc);
			bc.PropertyChanged += new PropertyChangedEventHandler(bc_PropertyChanged);
			NotifyPropertyChanged("Object Added");
		}
		#endregion
	}
}
